#!/usr/bin/php -B
<?php
/*
Free-Chao PHP IRC-Bot by Dr. Azrael Tod
partly based on:
- Sacred-Chao (Miranda-IM/PHP/mBot IRC-Bot) by Dr. Azrael Tod
- demonbot - a demonstation for codedemons.net
and small parts (google-api-search) of MoloBot 0.5 Beta By Jordan Smith - jordan@codedemons.net
*/

INCLUDE ('config.php');
$CONFIG['version'] = 'linux-20071205a-DAT'; //Version, only change if you change the source


/*
*******************************************************
MAIN SOURCECODE FOLLOWING, NO MORE CONFIGURATION NEEDED
*******************************************************

 /------------------------------------------\
<  only change if you know what you'r doing  >
 \------------------------------------------/
*/

  for ($i=count($modules)-1;$i>=0;$i--)
  {
   $file = $CONFIG['module-dir'].'/'.$modules[$i].'/require.php';
   if(file_exists($file))
   {
     echo $CONFIG['NET-Name'].": module ".$modules[$i]." has been installed\n\r";
     require_once($file);
   }
	else
	{
	echo $CONFIG['NET-Name'].": error loading module:  ".$modules[$i]." \n\r";
	echo $file."\n\r";
	}
  }

/* Let it run forever (no timeouts) */
set_time_limit(0);

/* The connection */
$con = array();

/* start the bot... */
init();

// Initialise the IRC bot.
function init()
{
	global $con, $CONFIG, $chans;
	/* We need this to see if we need to JOIN (the channel) during
	the first iteration of the main loop */
	$firstTime = true;
	$notpinged = 0;
	
	/* Connect to the irc server */
	$con['socket'] = fsockopen($CONFIG['server'], $CONFIG['port']);
	
	/* Check that we have connected */
	if (!$con['socket']) {
		print ("Could not connect to: ". $CONFIG['server'] ." on port ". $CONFIG['port']);
	} else {
		/* Send the username and nick */
		cmd_send("USER ". $CONFIG['name'] ." fh-zwickau.de fh-zwickau.de :". $CONFIG['name']); //notiz: eigenerdns, serverdns
		cmd_send("NICK ". $CONFIG['nick'] ." ".$CONFIG['nickserv-paswd']);
		
		/* Here is the loop. Read the incoming data (from the socket connection) */
		while (!feof($con['socket']))
		{
      /* Think of $con['buffer']['all'] as a line of chat messages.
			We are getting a 'line' and getting rid of whitespace around it. */
			$con['buffer']['all'] = trim(fgets($con['socket'], 4096));
			
			/* Pring the line/buffer to the console
			I used <- to identify incoming data, -> for outgoing. This is so that
			you can identify messages that appear in the console. */
			print "< ".$con['buffer']['all'] ."\n";
			
			/* If the server is PINGing, then PONG. This is to tell the server that
			we are still here, and have not lost the connection */
			if(substr($con['buffer']['all'], 0, 6) == 'PING :') {
				/* PONG : is followed by the line that the server
				sent us when PINGing */
				cmd_send('PONG :'.substr($con['buffer']['all'], 6));
				$notpinged=0;
				/* If this is the first time we have reached this point,
				then JOIN the channel */
				if ($firstTime == true){
					cmd_send('PRIVMSG Nickserv :identify '.$CONFIG['nickserv-paswd']);
					/* The next time we get here, it will NOT be the firstTime */
					$firstTime = false;
					//joining additional Channels
					
          for ($i=count($chans);$i>=0;$i--)
  					cmd_send("JOIN ".$chans[$i]);
				}
				/* Make sure that we have a NEW line of chats to analyse. If we don't,
				there is no need to parse the data again */
			}
			else if ($old_buffer != $con['buffer']['all'])
			{
				//
				// Log channel chat to file, mysql, or not at all
				//
				if ($CONFIG['log_type'] == "file")
				{
					// prep some data to log.
					$to_log = $CONFIG['NET-Name'];
					$to_log .= "[". date("d-j-y@H:i:s") ."]";
					$to_log .= " ". $con['buffer']['username'];
					$to_log .= ": ". $con['buffer']['text'] ."\r\n";
					// now log the data
					log_to_file($to_log);
				}
				else if ($CONFIG['log_type'] == "mysql")
				{
					// log to mysql
					log_to_mysql($con['buffer']['channel'], $con['buffer']['username'], $con['buffer']['text']);
				}
				// no loggin
				
				/* Determine the patterns to be passed
				to parse_buffer(). buffer is in the form:
				:username!~identd@hostname JOIN :#php
				:username!~identd@hostname PRIVMSG #PHP :action text
				:username!~identd@hostname command channel :text */
				
				// log the buffer to "log.txt" (file must have
				// already been created).
				// log_to_file($con['buffer']['all']);
				
				// make sense of the buffer
				parse_buffer();
				
				// now process any commands issued to the bot
				process_commands();
			}
			else
			{
			 $notpinged = $notpinged +1;
			 if ($notpinged > $CONFIG['wait_before_timeout'])
			    {
			                        cmd_send("QUIT :".$CONFIG['quit_msg']);
			    }
			}
			$old_buffer = $con['buffer']['all'];
		}
	}
}

/* Accepts the command as an argument, sends the command
to the server, and then displays the command in the console
for debugging */
function cmd_send($command)
{
	global $con, $time, $CONFIG;
	if($CONFIG['msg_max_length']>=strlen($command))
	{
		/* Send the command. Think of it as writing to a file. */
		fputs($con['socket'], $command."\n\r");
		/* Display the command locally, for the sole purpose
		of checking output. (line is not actually not needed) */
		print ("> ". $command. "\n\r");
	} else
	{
		fputs($con['socket'], substr($command,0,$CONFIG['msg_max_length'])."\n\r");
		/* Display the command locally, for the sole purpose
		of checking output. (line is not actually not needed) */
		print ($CONFIG['NET-Name']."> ". substr($command,0,$CONFIG['msg_max_length']). "\n\r");
		print ("! command to long");
	}
	
}

/*
Log the data that is passed to this function to
a file, right now, log.txt
*/
function log_to_file ($data)
{
	global $CONFIG;
	
	// open the log file
	if ($fp = fopen($CONFIG['file_name'], "ab"))
    {
        // now write to the file
        if ((fwrite($fp, $data) === FALSE))
        {
            echo 'Could not write to file./n';
        }
    }
    else
    {
        echo 'File could not be opened. /n';
    }
}

/*
Log the data that is passed to this function to the
mysql database. The table must already exist.
*/
function log_to_mysql($channel, $username, $test)
{
	global $CONFIG;
	
	$query = "INSERT INTO ". $CONFIG['table'] ." (time, channel, username, text)
		VALUES ('". time() ."', '". $channel ."', '". $username ."', '". $test ."')";
	mysql_query($query);
}

function process_commands()
{
	global $con, $modules, $CONFIG;
	$args = explode(" ", $con['buffer']['text']);
	
 //command-list part 1
	if(strtoupper($args[0]) == "!COMMANDS")
	{
		$COMMANDS="[!COMMANDS]";
	}
	
  for ($modulecount=count($modules)-1;$modulecount>=0;$modulecount--)
  {
  $file = $CONFIG['module-dir']."/".$modules[$modulecount]."/".'run.php';
   if(file_exists($file))
   {
     INCLUDE($file);
   }
	else
	{
	echo "error loading module:  ".$modules[$modulecount]."\n\r";
	echo $file."\n\r";
	}
  }

//command-list part 2
	if(strtoupper($args[0]) == "!COMMANDS")
	{
		cmd_send(prep_text("Commands",$COMMANDS));
		cmd_send(prep_text("INFO",'[] = contains sub-commands'));
	}
}  


function parse_buffer()
{
	
	/*
	:username!~identd@hostname JOIN :#php
	:username!~identd@hostname PRIVMSG #PHP :action text
	:username!~identd@hostname command channel :text
	*/
	
	global $con, $CONFIG;
		
	$buffer = $con['buffer']['all'];
	$buffer = explode(" ", $buffer, 4);
	
	/* Get username */
	$buffer['username'] = substr($buffer[0], 1, strpos($buffer['0'], "!")-1);
	
	/* Get identd */
	$posExcl = strpos($buffer[0], "!");
	$posAt = strpos($buffer[0], "@");
	$buffer['identd'] = substr($buffer[0], $posExcl+1, $posAt-$posExcl-1);
	$buffer['hostname'] = substr($buffer[0], strpos($buffer[0], "@")+1);
	
	/* The user and the host, the whole shabang */
	$buffer['user_host'] = substr($buffer[0],1);
	
	/* Isolate the command the user is sending from
	the "general" text that is sent to the channel
	This is  privmsg to the channel we are talking about.
	
	We also format $buffer['text'] so that it can be logged nicely.
	*/
	switch (strtoupper($buffer[1]))
	{
		case "JOIN":
		   	$buffer['text'] = "*JOINS: ". $buffer['username']." ( ".$buffer['user_host']." )";
			$buffer['command'] = "JOIN";
			$buffer['channel'] = $CONFIG['channel'];
		   	break;
		case "QUIT":
		   	$buffer['text'] = "*QUITS: ". $buffer['username']." ( ".$buffer['user_host']." )";
			$buffer['command'] = "QUIT";
			$buffer['channel'] = $CONFIG['channel'];
		   	break;
		case "NOTICE":
		   	$buffer['text'] = "*NOTICE: ". $buffer['username'];
			$buffer['command'] = "NOTICE";
			$buffer['channel'] = substr($buffer[2], 1);
		   	break;
		case "PART":
		  	$buffer['text'] = "*PARTS: ". $buffer['username']." ( ".$buffer['user_host']." )";
			$buffer['command'] = "PART";
			$buffer['channel'] = $CONFIG['channel'];
		  	break;
		case "MODE":
		  	$buffer['text'] = $buffer['username']." sets mode: ".$buffer[3];
			$buffer['command'] = "MODE";
			$buffer['channel'] = $buffer[2];
		break;
		case "NICK":
			$buffer['text'] = "*NICK: ".$buffer['username']." => ".substr($buffer[2], 1)." ( ".$buffer['user_host']." )";
			$buffer['command'] = "NICK";
			$buffer['channel'] = $CONFIG['channel'];
		break;
		
		default:
			// it is probably a PRIVMSG
			$buffer['command'] = $buffer[1];
			$buffer['channel'] = $buffer[2];
			$buffer['text'] = substr($buffer[3], 1);	
		break;	
	}
	$con['buffer'] = $buffer;
}

function prep_text($type, $message)
{
	global $con;
	if ($type=='')
  {
   	return ('PRIVMSG '. $con['buffer']['channel'] .' :'.$message);
 	}
 	else
 		return ('PRIVMSG '. $con['buffer']['channel'] .' :['.$type.'] '.$message);
}

function prep_text2($message, $target)
{
	global $con;
	return ('PRIVMSG '. $target .' :'.$message);
}



function trashfilter($nick, $text)
{ //filters unwanted things from History and prevents execution of recoursive running of commands
global $CONFIG, $con;
 $ret=true;
 if ($nick==$CONFIG['nick']) $ret=false;
 if ($nick=='[lovebase5]') $ret=false;
 if ($nick=='Chanserv') $ret=false;
 if ($nick=='Nickserv') $ret=false;
 if ($nick=='Memoserv') $ret=false;
 if (strpos($text,'notice')) $ret=false;
 if (strpos($text,'!showme')) $ret=false;
 return $ret;
}

	

?>
